package com.example.mybleapp;

import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;


import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class MainActivity extends AppCompatActivity {
    private final String TAG = "MainActivity";
    public String HEART_RATE_MEASUREMENT = "6e400003-e592-9ea6-b381-7431cb18605e";
    private String mDeviceAddress;
    private static final int REQUEST_ENABLE_BT = 1;
    private BluetoothLeScanner scanner;
    private BluetoothAdapter bluetoothAdapter;
    private LeDeviceListAdapter mleDeviceListAdapter;
    private static BluetoothLeService mBluetoothLeService;
    private MyInterface myInterface = new MyInterface();
    private FileOperation mFileOperation = new FileOperation();
    private ArrayList<Integer> rssis;
    private Handler myhandler = new Handler();
    private AlertDialog dialog;
    private boolean mScanning;
    private boolean mConnected = false;
    private static final long SCAN_PERIOD = 10000;
    private TextView tv_show;
    private ScrollView sv_show;
    private Button start_stop;
    //File dir = new File(getExternalFilesDir(Environment.getExternalStorageState()),"Data");
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_show = findViewById(R.id.tv_show);
        sv_show = findViewById(R.id.sv_show);
        start_stop = findViewById(R.id.start_stop);
        myInterface.setCollect(false);
        //动态申请权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
            }
        }
        //检查设备是否支持低功耗蓝牙
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
            finish();
        }
        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        if(bluetoothManager != null){
            bluetoothAdapter = bluetoothManager.getAdapter();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        //如果蓝牙未打开，打开蓝牙
        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if(myInterface.getCollect()){
            start_stop.setText("停止采集");
        } else {
            start_stop.setText("开始采集");
        }

    }

    private ScanCallback mLeScanCallback = new ScanCallback() {
        //当一个蓝牙ble广播被发现时回调
        @Override
        public void onScanResult(int callbackType, final ScanResult result) {
            super.onScanResult(callbackType, result);
            //扫描类型有开始扫描时传入的ScanSettings相关
            //对扫描到的设备进行操作。如：获取设备信息。
            runOnUiThread(new Runnable() {
                @Override
                public void run()
                {
                    mleDeviceListAdapter.addDevice(result.getDevice(),result.getRssi());
                    mleDeviceListAdapter.notifyDataSetChanged();
                }
            });
            System.out.println("Address:" + result.getDevice().getAddress());
            System.out.println("Name:" + result.getDevice().getName());
            System.out.println("rssi:" + result.getRssi());
        }

        //当扫描不能开启时回调
//        @Override
//        public void onScanFailed(int errorCode) {
//            super.onScanFailed(errorCode);
//            //扫描太频繁会返回ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED，表示app无法注册，无法开始扫描。
//
//        }
    };

    public void onCreateDialog() {
        mleDeviceListAdapter = new LeDeviceListAdapter();
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("蓝牙设备")
                .setAdapter(mleDeviceListAdapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //String info = mArrayAdapter.getItem(which);
                        if (mScanning) {
                            scanner.stopScan(mLeScanCallback);
                            mScanning = false;
                        }
                        mDeviceAddress = mleDeviceListAdapter.getDevice(which).getAddress();
                        Intent gattServiceIntent = new Intent(MainActivity.this, BluetoothLeService.class);
                        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
                        registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
                        if (mBluetoothLeService != null) {
                            final boolean result = mBluetoothLeService.connect(mDeviceAddress);
                            Log.d(TAG, "Connect request result=" + result);
                        }
                    }
                });
        dialog = builder.show();
    }

    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
                mConnected = true;
                Toast.makeText(MainActivity.this,"连接成功",Toast.LENGTH_SHORT).show();
                System.out.println("BroadcastReceiver :" + "device connected");
            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
                mConnected = false;
                Toast.makeText(MainActivity.this,"连接断开",Toast.LENGTH_SHORT).show();
                System.out.println("BroadcastReceiver :" + "device disconnected");
            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
                // Show all the supported services and characteristics on the
                // user interface.
                displayGattServices(mBluetoothLeService.getSupportedGattServices());
                System.out.println("BroadcastReceiver :" + "device SERVICES_DISCOVERED");
            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
                if(myInterface.getCollect()){
                    int[] ReceiveData = Objects.requireNonNull(intent.getExtras()).getIntArray(BluetoothLeService.EXTRA_DATA);
                    if(ReceiveData != null){
                        String data = "\nax:"+ReceiveData[0]+" ay:"+ReceiveData[1]+" az:"+ReceiveData[2]+" gx:"+ReceiveData[3]+" gy:"+ReceiveData[4]+" gz:"+ReceiveData[5];
                        displayData(data);
                        mFileOperation.SaveFile(data);
                    }
                }
                //System.out.println("BroadcastReceiver onData:" + intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
            }
        }
    };

    private void displayData(final String rev_data) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //Log.i("Receive data ", Arrays.toString(rev_data));
                tv_show.append(rev_data);
                //tv_show.append(rev_string+"\n");
                sv_show.scrollBy(0, tv_show.getMeasuredHeight());
            }
        });

    }

    private static IntentFilter makeGattUpdateIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
        return intentFilter;
    }

    private void displayGattServices(List<BluetoothGattService> gattServices) {
        if (gattServices == null) return;
        // Loops through available GATT Services.
        for (BluetoothGattService gattService : gattServices) {
            List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
            for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
                if (gattCharacteristic.getUuid().toString().equals(HEART_RATE_MEASUREMENT)) {
                    myhandler.postDelayed(new Runnable()
                    {
                        @Override
                        public void run() {
                            mBluetoothLeService.readCharacteristic(gattCharacteristic);
                        }
                    }, 200);
                    mBluetoothLeService.setCharacteristicNotification(gattCharacteristic, true);
                }
                List<BluetoothGattDescriptor> descriptors = gattCharacteristic.getDescriptors();
                for (BluetoothGattDescriptor descriptor : descriptors)
                {
                    System.out.println("---descriptor UUID:" + descriptor.getUuid());
                    mBluetoothLeService.getCharacteristicDescriptor(descriptor);
                }
            }
        }
    }

    private final ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
            if (!mBluetoothLeService.initialize()) {
                Log.e(TAG, "Unable to initialize Bluetooth");
                finish();
            }
            // Automatically connects to the device upon successful start-up
            mBluetoothLeService.connect(mDeviceAddress);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mBluetoothLeService = null;
        }
    };

    private void scanLeDevice() {
        if(bluetoothAdapter != null) {
            scanner = bluetoothAdapter.getBluetoothLeScanner();
        }
        // Stops scanning after a pre-defined scan period.
        myhandler.postDelayed(new Runnable() {
           @Override
           public void run() {
               mScanning = false;
               Log.i("SCAN", "stop.....................");
               scanner.stopScan(mLeScanCallback);
               Log.i(TAG, String.valueOf(mleDeviceListAdapter.getCount()));
               if(mleDeviceListAdapter.getCount() == 0){
                   dialog.dismiss();
                   Toast.makeText(MainActivity.this,"未发现蓝牙设备",Toast.LENGTH_LONG).show();
               }
           }
        }, SCAN_PERIOD);
        Log.i("SCAN", "begin.....................");
        mScanning = true;
        scanner.startScan(mLeScanCallback);
    }

    private class LeDeviceListAdapter extends BaseAdapter {
        private ArrayList<BluetoothDevice> mLeDevices;
        private LayoutInflater mInflator;
        LeDeviceListAdapter() {
            super();
            rssis = new ArrayList<>();
            mLeDevices = new ArrayList<>();
            mInflator = getLayoutInflater();
        }

        void addDevice(BluetoothDevice device, int rssi) {
            if (!mLeDevices.contains(device)) {
                mLeDevices.add(device);
                rssis.add(rssi);
            }
        }

        BluetoothDevice getDevice(int position) {
            return mLeDevices.get(position);
        }

        public void clear() {
            mLeDevices.clear();
            rssis.clear();
        }

        @Override
        public int getCount() {
            return mLeDevices.size();
        }

        @Override
        public Object getItem(int i) {
            return mLeDevices.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @SuppressLint({"ViewHolder", "InflateParams"})
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            // General ListView optimization code.
            view = mInflator.inflate(R.layout.device_item,null);
            TextView deviceAddress = view.findViewById(R.id.tv_deviceAddr);
            TextView deviceName = view.findViewById(R.id.tv_deviceName);
            TextView rssi = view.findViewById(R.id.tv_rssi);

            BluetoothDevice device = mLeDevices.get(i);
            deviceAddress.setText(device.getAddress());
            deviceName.setText(device.getName());
            rssi.setText(String.valueOf(rssis.get(i)));

            return view;
        }
    }

    public void onScan(View view) {
        onCreateDialog();
        scanLeDevice();
    }

    public void onShowChart(View view) {
        Intent chartintent = new Intent(MainActivity.this, ChartActivity.class);
        startActivity(chartintent);
    }

    public void onStart(View view) {
        if(mConnected){
            if(myInterface.getCollect()){
                myInterface.setCollect(false);
                start_stop.setText("开始采集");
                String file = mFileOperation.CloseFile();
                if(file != null){
                    tv_show.append("\n保存路径为："+file);
                }
            }else{
                myInterface.setCollect(true);
                start_stop.setText("停止采集");
                File file = getExternalFilesDir(Environment.getExternalStorageState());
                mFileOperation.OpenFile(file);
            }
        } else {
            Toast.makeText(MainActivity.this,"请先连接到蓝牙设备",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);
        unregisterReceiver(mGattUpdateReceiver);
        mFileOperation.CloseFile();
        mBluetoothLeService = null;
    }

}
